using System;
using System.Text;
using System.Text.RegularExpressions;
using System.Collections;

namespace umlungu.engineX.pop3X {
	/// <summary>
	/// umlungu engineX blog Pop3 class.
	/// </summary>
	public class x_pop3body
	{
		/// <summary>
		/// Local objects and properties
		/// </summary>
		private ArrayList _component = new ArrayList();
		public IEnumerator ComponentEnumerator {	get { return _component.GetEnumerator(); }}
		public int NumberOfComponents {	get { return _component.Count; }}

		public x_pop3body(string[] lines, long startOfBody, string multipartBoundary, string mainContentType) {
			long stopOfBody = lines.Length;
			// if this email is a mixture of message and attachments ...
			if(multipartBoundary == null) {
				StringBuilder sbText = new StringBuilder();
				for(long i=startOfBody; i<stopOfBody; i++) {
					sbText.Append(lines[i].Replace("\n","").Replace("\r",""));
				}
				// create a new component ...
				_component.Add(new x_pop3att( mainContentType, sbText.ToString()));
			} else {				
				string boundary = multipartBoundary;
				bool firstComponent = true;

				// loop through whole of email ...
				for(long i=startOfBody; i<stopOfBody;) {
					bool boundaryFound = true;
					string contentType = null;
					string name = null;
					string filename = null;
					string contentTransferEncoding= null;
					string contentDescription = null;
					string contentDisposition = null;
					string data = null;

					// if first block of multipart data ...
					if( firstComponent ) {
						boundaryFound = false;
						firstComponent = false;

						while( i<stopOfBody ) {
							string line = lines[i].Replace("\n","").Replace("\r","");
							// if multipart boundary found then exit loop ...
							if( x_pop3parse.GetSubHeaderLineType(line,boundary) ==
								x_pop3parse.MultipartBoundaryFound ) {
								boundaryFound = true;
								++i;
								break;
							} else {	// ... else read next line ...
								++i;
							}
						}
					}

					// check to see whether multipart boundary
					// was found ...

					if(!boundaryFound) {
						throw(new x_exception("error_pop3_boundary", "Missing multipart boundary: "+boundary));
					}

					bool endOfHeader = false;

					// read header information ...
					while( (i<stopOfBody) ) {
						string line = lines[i].Replace("\n","").Replace("\r","");
						int lineType = x_pop3parse.GetSubHeaderLineType(line,boundary);
						switch(lineType) {
							case x_pop3parse.ContentTypeType :
								contentType = x_pop3parse.ContentType(line);
								break;
							case x_pop3parse.ContentTransferEncodingType :
								contentTransferEncoding = x_pop3parse.ContentTransferEncoding(line);
								break;
							case x_pop3parse.ContentDispositionType :
								contentDisposition = x_pop3parse.ContentDisposition(line);
								break;
							case x_pop3parse.ContentDescriptionType :
								contentDescription = x_pop3parse.ContentDescription(line);
								break;
							case x_pop3parse.EndOfHeader :
								endOfHeader = true;
								break;
						}
						++i;

						if(endOfHeader) {
							break;
						} else {
							while(i<stopOfBody) {
								// if more lines to read for this line ...
								if(line.Substring(line.Length-1,1).Equals(";")) {
									string nextLine = lines[i].Replace("\r","").Replace("\n","");
									switch( x_pop3parse.GetSubHeaderNextLineType(nextLine) ) {
										case x_pop3parse.NameType:
											name = x_pop3parse.Name(nextLine);
											break;
										case x_pop3parse.FilenameType:
											filename = x_pop3parse.Filename(nextLine);
											break;
										case x_pop3parse.EndOfHeader:
											endOfHeader = true;
											break;
									}

									if( !endOfHeader ) {
										// point line to current line ...
										line = nextLine;
										++i;
									} else {
										break;
									}
								} else {
									break;
								}
							}
						}
					}
					boundaryFound = false;
					StringBuilder sbText = new StringBuilder();
					bool emailComposed = false;

					// store the actual data ...
					while(i<stopOfBody) {
						// get the next line ...
						string line = lines[i].Replace("\n","");

						// if we've found the boundary ...
						if( x_pop3parse.GetSubHeaderLineType(line,boundary) ==
							x_pop3parse.MultipartBoundaryFound ) {
							boundaryFound = true;
							++i;
							break;
						} else if( x_pop3parse.GetSubHeaderLineType(line,boundary) == x_pop3parse.ComponentsDone ) {
							emailComposed = true;
							break;
						}
						
						// add this line to data ...
						sbText.Append(lines[i]);
						++i;
					}

					if(sbText.Length>0) {
						data = sbText.ToString();
					}

					// create a new component ...
					_component.Add(new x_pop3att(contentType, name, filename, contentTransferEncoding, contentDescription, contentDisposition, data));

					// if all multiparts have been composed then exit ..
					if(emailComposed) {
						break;
					}
				}
			}
		}
	}
}
